package cn.edu.mju.auth.config;

import cn.edu.mju.auth.handler.TokenAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.sql.DataSource;

/**
 * @author 16423
 * 授权服务器配置
 */
@Configuration
@EnableAuthorizationServer
@Order(20)
public class JwtAuthServerConfig extends AuthorizationServerConfigurerAdapter {

    //密码加密
    private final PasswordEncoder passwordEncoder;

    //开启授权码模式需要注入authenticationManager
    private final AuthenticationManager authenticationManager;

    //设置数据源
    private final DataSource dataSource;

    //配置注入登录service
    private final UserDetailsService userDetailsService;

    //token认证入口
    private final TokenAuthenticationEntryPoint authenticationEntryPoint;



    @Autowired
    public JwtAuthServerConfig(PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, DataSource dataSource, UserDetailsService userDetailsService, TokenAuthenticationEntryPoint authenticationEntryPoint) {
        this.passwordEncoder = passwordEncoder;
        this.authenticationManager = authenticationManager;
        this.dataSource = dataSource;
        this.userDetailsService = userDetailsService;
        this.authenticationEntryPoint = authenticationEntryPoint;
    }


    /**
     * 设置Jwt模式
     * **/
    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * 配置jwt访问令牌转换器
     * **/
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //设置签名密钥
        converter.setSigningKey("123");
        return converter;
    }

    /**
     * 配置客户端
     * **/
    @Bean
    public ClientDetailsService clientDetails(){

        JdbcClientDetailsService jdbcClientDetailsService= new JdbcClientDetailsService(dataSource);
        jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);

        return jdbcClientDetailsService;
    }


    /**
     * 修改安全配置
     * **/
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
        // 客户端设置身份验证管理器
        filter.setAuthenticationManager(authenticationManager);
        // 客户端配置自定义异常处理
        filter.setAuthenticationEntryPoint(authenticationEntryPoint);
        filter.afterPropertiesSet();

        security
                // 开启表单认证
                .allowFormAuthenticationForClients()
                // 开启 /oauth/token_key 验证端口     无权限访问
                .tokenKeyAccess("permitAll()")
                // 开启 /oauth/check_token 验证端口   无权限访问
                .checkTokenAccess("permitAll()")
                // 添加自定义拦截器
                .addTokenEndpointAuthenticationFilter(filter);
    }

    /**
     * 为认证端点配置基本信息
     * **/
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .accessTokenConverter(jwtAccessTokenConverter())
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);

    }

    /**
     * 添加客户端
     * */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.withClientDetails(clientDetails());

    }


}
////http://localhost:8888/sso/oauth/authorize?client_id=client&response_type=code&redirect_uri=https://www.baidu.com
////curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=authorization_code&code=7ZviX8&redirect_uri=https://www.baidu.com' http:/client:secret@localhost:8888/oauth/token
